home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 3 / Cream of the Crop 3.iso / comm / wnos5src.zip / CMDPARSE.C < prev    next >
Text File  |  1993-08-09  |  7KB  |  333 lines

  1. /* Parse command line, set up command arguments Unix-style, and call function.
  2.  * Note: argument is modified (delimiters are overwritten with nulls)
  3.  * Improved error handling by Brian Boesch of Stanford University
  4.  */
  5. #include <stdio.h>
  6. #include <ctype.h>
  7. #include "global.h"
  8. #include "config.h"
  9. #include "proc.h"
  10. #include "cmdparse.h"
  11.  
  12. static char * near
  13. stringparse(char *line)
  14. {
  15.     char num, *cp = line;
  16.  
  17.     while(*line != '\0' && *line != '\"') {
  18.         if(*line == '\\') {
  19.             line++;
  20.             switch ( *line++ ) {
  21.             case 'n':
  22.                 *cp++ = '\n';
  23.                 break;
  24.             case 't':
  25.                 *cp++ = '\t';
  26.                 break;
  27.             case 'v':
  28.                 *cp++ = '\v';
  29.                 break;
  30.             case 'b':
  31.                 *cp++ = '\b';
  32.                 break;
  33.             case 'r':
  34.                 *cp++ = '\r';
  35.                 break;
  36.             case 'f':
  37.                 *cp++ = '\f';
  38.                 break;
  39.             case 'a':
  40.                 *cp++ = '\a';
  41.                 break;
  42.             case '\\':
  43.                 *cp++ = '\\';
  44.                 break;
  45.             case '\?':
  46.                 *cp++ = '\?';
  47.                 break;
  48.             case '\'':
  49.                 *cp++ = '\'';
  50.                 break;
  51.             case '\"':
  52.                 *cp++ = '\"';
  53.                 break;
  54.             case 'x':
  55.                 num = strtoul( --line, &line, 16 );
  56.                 *cp++ = num;
  57.                 break;
  58.             case '0':
  59.             case '1':
  60.             case '2':
  61.             case '3':
  62.             case '4':
  63.             case '5':
  64.             case '6':
  65.             case '7':
  66.                 num = strtoul( --line, &line, 8 );
  67.                 *cp++ = num;
  68.                 break;
  69.             case '\0':
  70.                 return NULLCHAR;
  71.             default:
  72.                 *cp++ = *(line - 1);
  73.                 break;
  74.             };
  75.         } else {
  76.             *cp++ = *line++;
  77.         }
  78.     }
  79.  
  80.     if(*line == '\"')
  81.         line++;     /* skip final quote */
  82.     *cp = '\0';        /* terminate string */
  83.     return line;
  84. }
  85.  
  86. int
  87. cmdparse(struct cmds cmds[],char *line,void *p)
  88. {
  89.     struct cmds *cmdp;
  90.     char *argv[NARG], *cp;
  91.     int argc, i;
  92.  
  93.     /* Remove cr/lf */
  94.     rip(line);
  95.  
  96.     for(argc = 0; argc < NARG; argc++)
  97.         argv[argc] = NULLCHAR;
  98.  
  99.     for(argc = 0; argc < NARG; ) {
  100.         int qflag = FALSE;
  101.  
  102.         /* Skip leading white space */
  103.         while(*line == ' ' || *line == '\t')
  104.             line++;
  105.         if(*line == '\0')
  106.             break;
  107.         /* Check for quoted token */
  108.         if(*line == '"'){
  109.             line++;    /* Suppress quote */
  110.             qflag = TRUE;
  111.         }
  112.         argv[argc++] = line;    /* Beginning of token */
  113.  
  114.         if(qflag){
  115.             /* Find terminating delimiter */
  116.             if((line = stringparse(line)) == NULLCHAR){
  117.                 return -1;
  118.             }
  119.         } else {
  120.             /* Find space or tab. If not present,
  121.              * then we've already found the last
  122.              * token.
  123.              */
  124.             if((cp = strpbrk(line," \t")) == NULL)
  125.                 break;
  126.  
  127.             *cp++ = '\0';
  128.             line = cp;
  129.         }
  130.     }
  131.     if(argc < 1) {        /* empty command line */
  132.         argc = 1;
  133.         argv[0] = "";
  134.     }
  135.     /* Lines beginning with "#" are comments */
  136.     if(argv[0] == NULLCHAR || argv[0][0] == '#')
  137.         return 0;
  138.  
  139.     /* Look up command in table; prefix matches are OK */
  140.     for(cmdp = cmds; cmdp->name != NULLCHAR; cmdp++){
  141.         if(strncmp(*argv,cmdp->name,strlen(*argv)) == 0)
  142.             break;
  143.     }
  144.     if(cmdp->name == NULLCHAR) {
  145.         if(cmdp->argc_errmsg != NULLCHAR)
  146.             tprintf("%s\n",cmdp->argc_errmsg);
  147.         return -1;
  148.     } else {
  149.         if(argc < cmdp->argcmin) {
  150.             /* Insufficient arguments */
  151.             tprintf("Usage: %s\n",cmdp->argc_errmsg);
  152.             return -1;
  153.         } else {
  154.             if(cmdp->stksize == 0){
  155.                 return (*cmdp->func)(argc,argv,p);
  156.             } else {
  157.                 /* Make private copy of argv and args,
  158.                  * spawn off subprocess and return.
  159.                  */
  160.                 char **pargv = cxallocw(argc,sizeof(char *));
  161.  
  162.                 for(i = 0; i < argc; i++) {
  163.                     pargv[i] = strxdup(argv[i]);
  164.                 }
  165.                 newproc(cmdp->name,cmdp->stksize,
  166.                     (void (*)())cmdp->func,argc,pargv,p,1);
  167.                 return(0);
  168.             }
  169.         }
  170.     }
  171. }
  172.  
  173. /* Call a subcommand based on the first token in an already-parsed line */
  174. int
  175. subcmd(struct cmds tab[],int argc,char **argv,void *p)
  176. {
  177.     struct cmds *cmdp;
  178.     int i, found = 0;
  179.  
  180.     /* Strip off first token and pass rest of line to subcommand */
  181.     if(argc < 1) {
  182.         tputs("SUBCMD - Don't know what to do\n");
  183.         return -1;
  184.     }
  185.     if(argc > 1) {
  186.         argc--;
  187.         argv++;
  188.         for(cmdp = tab; cmdp->name != NULLCHAR; cmdp++) {
  189.             if(strncmp(*argv,cmdp->name,strlen(*argv)) == 0){
  190.                 found = 1;
  191.                 break;
  192.             }
  193.         }
  194.     }
  195.     if(!found) {
  196.         tputs("available subcommands:\n");
  197.         for(i = 0, cmdp = tab; cmdp->name != NULLCHAR; cmdp++, i = (i+1)%5)
  198.             tprintf("%-15.15s%s",cmdp->name,(i == 4) ? "\n" : "");
  199.  
  200.         if(i)
  201.             tputs("\n");
  202.         return -1;
  203.     }
  204.     if(argc < cmdp->argcmin){
  205.         if(cmdp->argc_errmsg != NULLCHAR)
  206.             tprintf("Usage: %s\n",cmdp->argc_errmsg);
  207.         return -1;
  208.     }
  209.     if(cmdp->stksize == 0){
  210.         return (*cmdp->func)(argc,argv,p);
  211.     } else {
  212.         /* Make private copy of argv and args */
  213.         char **pargv = cxallocw(argc,sizeof(char *));
  214.  
  215.         for(i = 0; i < argc; i++) {
  216.             pargv[i] = strxdup(argv[i]);
  217.         }
  218.         newproc(cmdp->name,cmdp->stksize,
  219.             (void (*)())cmdp->func,argc,pargv,p,1);
  220.         return(0);
  221.     }
  222. }
  223.  
  224. /* Subroutine for setting and displaying boolean flags */
  225. int
  226. setbool(int *var,char *label,int argc,char **argv)
  227. {
  228.     static struct boolcmd {
  229.         char *str;            /* Token */
  230.         int val;            /* Value */
  231.     } Boolcmds[] = {
  232.         "yes",        TRUE,    /* Synonyms for "true" */
  233.         "true",        TRUE,
  234.         "on",        TRUE,
  235.         "1",        TRUE,
  236.         "set",        TRUE,
  237.         "enable",    TRUE,
  238.  
  239.         "no",        FALSE,    /* Synonyms for "false" */
  240.         "false",    FALSE,
  241.         "off",        FALSE,
  242.         "0",        FALSE,
  243.         "clear",    FALSE,
  244.         "disable",    FALSE,
  245.         NULLCHAR
  246.     };
  247.     struct boolcmd *bc;
  248.  
  249.     if(argc < 2){
  250.         tprintf("%s: %s\n",label,*var ? "on" : "off");
  251.         return 0;
  252.     }
  253.     for(bc = Boolcmds; bc->str != NULLCHAR; bc++) {
  254.         if(strnicmp(argv[1],bc->str,strlen(argv[1])) == 0) {
  255.             *var = bc->val;
  256.             return 0;
  257.         }
  258.     }
  259.     tputs("Valid options:");
  260.     for(bc = Boolcmds; bc->str != NULLCHAR; bc++) {
  261.         tprintf(" %s",bc->str);
  262.     }
  263.     tputs("\n");
  264.     return 1;
  265. }
  266.  
  267. /* Subroutine for setting and displaying long variables */
  268. int
  269. setlong(long *var,char *label,int argc,char **argv)
  270. {
  271.     if(argc < 2) {
  272.         tprintf("%s: %ld\n",label,*var);
  273.     } else {
  274.         *var = atol(argv[1]);
  275.     }
  276.     return 0;
  277. }
  278.  
  279. /* Subroutine for setting and displaying short variables */
  280. int
  281. setshort(unsigned short *var,char *label,int argc,char **argv)
  282. {
  283.     if(argc < 2) {
  284.         tprintf("%s: %u\n",label,*var);
  285.     } else {
  286.         *var = atoi(argv[1]);
  287.     }
  288.     return 0;
  289. }
  290.  
  291. /* Subroutine for setting and displaying integer variables */
  292. int
  293. setint(int *var,char *label,int argc,char **argv)
  294. {
  295.     if(argc < 2) {
  296.         tprintf("%s: %u\n",label,*var);
  297.     } else {
  298.         *var = atoi(argv[1]);
  299.     }
  300.     return 0;
  301. }
  302.  
  303. /* Subroutine for setting and displaying int variables (with range check) */
  304. int
  305. setintrc(int16 *var,char *label,int argc,char **argv,int minval,int16 maxval)
  306. {
  307.     if (argc < 2) {
  308.         tprintf("%s: %u\n", label, *var);
  309.     } else {
  310.         int16 tmp = atol(argv[1]);
  311.  
  312.         if(isalpha(*argv[1]) || tmp < minval || tmp > maxval) {
  313.             tprintf("%s must be %i..%i\n", label, minval, maxval);
  314.             return -1;
  315.         }
  316.         *var = tmp;
  317.     }
  318.     return 0;
  319. }
  320.  
  321. #ifdef MODEM
  322. /* Subroutine for setting and displaying unsigned integer variables */
  323. int
  324. setuns(unsigned *var,char *label,int argc,char **argv)
  325. {
  326.     if(argc < 2) {
  327.         tprintf("%s: %u\n",label,*var);
  328.     } else {
  329.         *var = (unsigned)atoi(argv[1]);
  330.     }
  331.     return 0;
  332. }
  333. #endif